package com.logicfishsoftware.wolfgo.meta.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.ByteBuffer;

import org.apache.commons.io.FilenameUtils;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.object.ObjectConnection;
import org.openrdf.store.blob.BlobObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.logicfishsoftware.wolfgo.api.VirtualContentConnection;
import com.logicfishsoftware.wolfgo.api.VirtualFileSystemException;

class SemanticContentConnection implements VirtualContentConnection {
	static Logger log = LoggerFactory.getLogger(SemanticContentConnection.class);
	private ObjectConnection connection;
	private String baseURI = "http://localhost/content";

	protected SemanticContentConnection(ObjectConnection connection) {
		this.connection = connection;
	}

	private String fileToURI(String fileName) {
		fileName = FilenameUtils.separatorsToUnix(fileName);
		if(fileName==null) return baseURI + "/";
		if(fileName.endsWith("/")) fileName = fileName.substring(0,fileName.length()-1);
		if("".equals(fileName)) return baseURI + "/";
		return baseURI + fileName;
	}

	public InputStream getInputStream(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		try {
			return connection.getBlobObject(uri).openInputStream();
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}
	}

	public Reader getReader(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		try {
			return connection.getBlobObject(uri).openReader(false);
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}
	}
	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#length(java.lang.String)
	 */
	@Override
	public long length(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		log.info("Get length " + uri);
		try {
//			return connection.getBlobObject(uri).getLength();
			CharSequence content = connection.getBlobObject(uri).getCharContent(true);
			if(content==null) {
				return 0;
			}
			return content.length();
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}
	}
	public long getLastModified(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		log.info("Get last modified " + uri);
		try {
			return connection.getBlobObject(uri).getLastModified();
		} catch (RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}
	}
	public OutputStream getOutputStream(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		try {
			BlobObject blobObject = connection.getBlobObject(uri);
			return blobObject.openOutputStream();
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}		
	}
	public Writer getWriter(String filename) throws VirtualFileSystemException {
		String uri = fileToURI(filename);
		try {
			BlobObject blobObject = connection.getBlobObject(uri);
			return blobObject.openWriter();
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}		
	}
	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#clear(java.lang.String)
	 */
	@Override
	public void clear(String uri) throws VirtualFileSystemException {
		try {
			BlobObject blobObject = connection.getBlobObject(uri);
			OutputStream outputStream = blobObject.openOutputStream();
			outputStream.flush();
			outputStream.close();
		} catch (IOException | RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}		
	}
	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#delete(java.lang.String)
	 */
	@Override
	public boolean delete(String uri) throws VirtualFileSystemException {
		try {
			BlobObject blobObject = connection.getBlobObject(uri);
			return blobObject.delete();
		} catch (RepositoryException e) {
			log.error("Error opening BlobObject.",e);
			throw new VirtualFileSystemException(e);
		}
		
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#read(java.lang.String, java.nio.ByteBuffer, long, int)
	 */
	@Override
	public void read(String fileName, ByteBuffer buffer, long offset,
			int copySize) throws VirtualFileSystemException {
		log.info("Read " + fileName + " length: "+copySize);
		InputStream stream = getInputStream(fileName);
		byte[] b = new byte[copySize];
		try {
			stream.read(b);
		} catch (IOException e) {
			log.error("Error during read:",e);
			throw new VirtualFileSystemException("Error during read",e);
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				log.warn("Error during close:",e);
			}
		}
		buffer.put(b);
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#write(java.lang.String, long, byte[], int, int)
	 */
	@Override
	public void write(String fileName, long offset, byte[] buff, int len, int overwriteSize) throws VirtualFileSystemException {
		log.info("Write " + fileName + " length "+len);
		OutputStream stream = getOutputStream(fileName);
		try {
			stream.write(buff, (int)offset, len);
			stream.flush();
		} catch (IOException e) {
			log.error("Error during write:",e);
			throw new SemanticFileSystemException("Error during write",e);
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				log.warn("Error during close:",e);
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#append(java.lang.String, byte[], int, int)
	 */
	@Override
	public void append(String fileName, byte[] buff, int overwriteSize, int len) throws VirtualFileSystemException {
		// TODO Logic for appending data
		log.info("Append " + fileName + " length "+len);
		OutputStream stream = getOutputStream(fileName);
		try {
			stream.write(buff, 0, len);
			stream.flush();
		} catch (IOException e) {
			log.error("Error during write:",e);
			throw new SemanticFileSystemException("Error during write",e);
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				log.warn("Error during close:",e);
			}
		}
		
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#append(java.lang.String, byte[])
	 */
	@Override
	public void append(String fileName, byte[] buf) {
		log.info("Append buffer " + fileName + " length "+buf.length);
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#truncate(java.lang.String, long)
	 */
	@Override
	public void truncate(String fileName, long length) {
		log.info("Truncate " + fileName + " length "+length);
		
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.wolfgo.meta.impl.ContentConnection#move(java.lang.String, java.lang.String)
	 */
	@Override
	public void move(String existingFileName, String newFileName) {
		log.info("Move " + existingFileName + " to "+newFileName);
	}

}
